# coding=utf-8
import logging

from common import orm
from common.utils import tz
from common.utils.decorator import sql_wrapper
from common.utils.db import list_object, get, upsert, delete, generate_filter
from common.withdraw.model import WithdrawChannel, WithdrawOrder, WITHDRAW_STATUS

from sqlalchemy import func, text

_LOGGER = logging.getLogger(__name__)


@sql_wrapper
def get_channels_in_ids(chn_ids):
    if not chn_ids:
        return []
    chns = WithdrawChannel.query.filter(WithdrawChannel.id.in_(chn_ids)).all()
    return chns


@sql_wrapper
def get_channel(id):
    return get(WithdrawChannel, id)


@sql_wrapper
def upsert_channel(info, id=None):
    return upsert(WithdrawChannel, info, id)


@sql_wrapper
def list_channel(query_dct):
    return list_object(query_dct, WithdrawChannel)


@sql_wrapper
def delete_channel(id):
    delete(WithdrawChannel, id)


@sql_wrapper
def get_order(id):
    return get(WithdrawOrder, id)


@sql_wrapper
def upsert_order(info, id=None):
    return upsert(WithdrawOrder, info, id)


@sql_wrapper
def list_order(query_dct):
    return list_object(query_dct, WithdrawOrder)


@sql_wrapper
def export_order(query_dct):
    items, _ = list_object(query_dct, WithdrawOrder, disable_paginate=True)
    resp_items = []
    for item in items:
        created_at = tz.utc_to_local_str(item.created_at)
        withdraw_at = tz.utc_to_local_str(item.withdraw_at)
        channel_obj = get_channel(item.channel_id) 
        status = WITHDRAW_STATUS.get_label(item.status)
        data_row = [item.id, item.out_trade_no, item.third_id or '-',
            created_at, item.mch_id, item.channel_id, channel_obj.app_id,
            channel_obj.name, item.total_fee, withdraw_at or '-', status]
        resp_items.append(data_row)
    return resp_items


@sql_wrapper
def get_order_overview(parsed_dct):
    query = orm.session.query(WithdrawOrder.channel_id,
                              func.count(WithdrawOrder), func.sum(WithdrawOrder.total_fee))
    query = query.filter(generate_filter(parsed_dct, WithdrawOrder))
    query = query.filter(WithdrawOrder.status==WITHDRAW_STATUS.SUCC)
    query = query.group_by(WithdrawOrder.channel_id)
    resp = []
    chn_ids = []
    for r in query.all():
        # (type, count , sum)
        resp.append({
            "channel_id": r[0] or parsed_dct.get('channel_id', 0),
            "count": r[1],
            "total": float(r[2]) if r[2] is not None else 0,
        })
        chn_ids.append(r[0])
    return resp, chn_ids


@sql_wrapper
def add_channel_balance(chn_id, money):
    chn = WithdrawChannel.query.filter(WithdrawChannel.id==chn_id).with_lockmode('update').first()
    if chn.balance is None:
        chn.balance = money
    else:
        chn.balance = float(chn.balance) + float(money)
    chn.save()
    return chn
